<template>
  <el-dialog
    :title="`${$t('AbpIdentity[\'Permissions\']')} - ${context.providerKey}`"
    :visible.sync="visible"
    :before-close="closeDialog"
    top="10vh"
  >
    <el-form v-loading="loading" label-position="top">
      <el-checkbox
        v-model="permissionData.checked"
        :indeterminate="permissionData.indeterminate"
        style="display: inline-block;margin-top:13px;margin-left:10px;"
        @change="permissionAllCheck"
      >
        {{ $t('BookStore2[\'SelectAllInAllTabs\']') }}
      </el-checkbox>
      <el-divider />
      <el-tabs v-model="activePaneName" tab-position="left">
        <el-tab-pane
          v-for="group in permissionData.groups"
          ref="tabPane"
          :key="group.name"
          :name="group.name"
          :label="`${group.displayName}(${group.checkedCount}/${group.permissions.length})`"
        >
          <el-checkbox
            v-model="group.checked"
            :indeterminate="group.indeterminate"
            style="display: inline-block;margin-top:13px;margin-left:10px;"
            @change="permissionGroupCheck"
          >
            {{ group.displayName }}
          </el-checkbox>
          <el-divider />
          <el-tree
            ref="permissionTree"
            :node-key="treeContext.nodeKey"
            :props="treeContext.props"
            :data="group.permissionTree"
            :expand-on-click-node="false"
            default-expand-all
            check-on-click-node
            check-strictly
            show-checkbox
            @check="treeCheck"
          />
        </el-tab-pane>
      </el-tabs>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="closeDialog">{{ $t('AbpIdentity[\'Cancel\']') }}</el-button>
      <el-button type="primary" @click="submitForm">{{ $t('AbpIdentity[\'Save\']') }}</el-button>
    </div>
  </el-dialog>
</template>

<script>
import {
  getPermission,
  edit
} from '@/api/administration/permission/permission'
export default {
  name: 'UserOrRolePermission',
  props: {
    context: {
      type: Object,
      required: true
    },
    visible: {
      type: Boolean,
      required: true,
      default: false
    }
  },
  data() {
    return {
      title: '',
      loading: false,
      activePaneName: '',
      treeContext: {
        props: {
          label: 'displayName',
          children: 'children'
        },
        nodeKey: 'name'
      },
      permissionData: {
        entityDisplayName: '',
        groups: []
      }
    }
  },
  computed: {
    activePaneIndex() {
      return this.$refs.tabPane.filter(item => item.name === this.activePaneName)[0].index
    }
  },
  watch: {
    context(newVal, oldVal) {
      this.loading = true
      getPermission(newVal.providerName, newVal.providerKey).then(resp => {
        this.permissionData = resp
        let groupCheckedCount = 0
        let groupIndeterminateCount = 0
        this.permissionData.groups.forEach((group, index) => {
          // 设置tab的默认pane
          if (index === 0) {
            this.activePaneName = group.name
          }

          // permission索引表
          const permissionMap = group.permissions.reduce((total, currentValue, currentIndex) => {
            total[currentValue.name] = currentIndex
            return total
          }, {})

          const checkedKeys = []
          group.permissionTree = []
          group.permissions.forEach(permission => {
            // 构造树结构
            if (permission.parentName) {
              const parent = group.permissions[permissionMap[permission.parentName]]
              parent.children = [...(parent.children || []), permission]
            } else {
              group.permissionTree.push(permission)
            }
            // 显示用户所属的角色权限
            if (newVal.providerName === 'U') {
              permission.grantedProviders.forEach(p => {
                if (p.providerName === 'R') {
                  permission.displayName += ` - [R:${p.providerKey}]`
                }
              })
            }
            // 收集已授权的权限
            if (permission.isGranted) {
              checkedKeys.push(permission.name)
            }
          })

          // 设置二级选项框状态
          this.$set(group, 'checkedCount', checkedKeys.length)
          this.$set(group, 'checked', checkedKeys.length === group.permissions.length)
          this.$set(group, 'indeterminate', checkedKeys.length !== 0 && checkedKeys.length < group.permissions.length)
          group.checked && groupCheckedCount++
          group.indeterminate && groupIndeterminateCount++

          this.$nextTick(() => this.$refs.permissionTree[index].setCheckedKeys(checkedKeys))
        })

        // 设置一级选项框状态
        this.$set(this.permissionData, 'checked', groupCheckedCount === this.permissionData.groups.length)
        this.$set(this.permissionData, 'indeterminate', (groupCheckedCount !== 0 && groupCheckedCount < this.permissionData.groups.length) || groupIndeterminateCount > 0)

        this.loading = false
      })
    }
  },
  methods: {
    permissionAllCheck(checked) {
      /* 一级选项框 */

      this.permissionData.indeterminate = false
      this.permissionData.groups.forEach((group, index) => {
        const permissionTree = this.$refs.permissionTree[index]
        this.setPermissionGroupCheck(group, permissionTree, checked)
      })
    },
    permissionGroupCheck(checked) {
      /* 二级选项框 */

      const permissionTree = this.$refs.permissionTree[this.activePaneIndex]
      const group = this.permissionData.groups[this.activePaneIndex]
      this.setPermissionGroupCheck(group, permissionTree, checked)

      // 设置一级选项框状态
      const groupCheckedCount = this.permissionData.groups.filter(g => g.checked).length
      this.permissionData.checked = groupCheckedCount === this.permissionData.groups.length
      this.permissionData.indeterminate = groupCheckedCount !== 0 && groupCheckedCount < this.permissionData.groups.length
    },
    treeCheck(dataNode) {
      /* 三级选项框 */

      const group = this.permissionData.groups[this.activePaneIndex]
      const tree = this.$refs.permissionTree[this.activePaneIndex]
      const treeNode = tree.getNode(dataNode.name)
      if (treeNode.checked) {
        this.setCheckedParentRecursion(treeNode)
      } else {
        this.setUnCheckedChildRecursion(treeNode)
      }

      // 设置二级选项框状态
      const checkedKeys = tree.getCheckedKeys()
      group.checked = checkedKeys.length === group.permissions.length
      group.indeterminate = checkedKeys.length !== 0 && checkedKeys.length < group.permissions.length
      group.checkedCount = checkedKeys.length

      // 设置一级选项框状态
      let groupCheckedCount = 0
      let groupIndeterminateCount = 0
      this.permissionData.groups.forEach(g => {
        g.checked && groupCheckedCount++
        g.indeterminate && groupIndeterminateCount++
      })
      this.permissionData.checked = groupCheckedCount === this.permissionData.groups.length
      this.permissionData.indeterminate = (groupCheckedCount !== 0 && groupCheckedCount < this.permissionData.groups.length) || groupIndeterminateCount > 0
    },
    setPermissionGroupCheck(group, permissionTree, checked) {
      if (checked) {
        permissionTree.setCheckedNodes(group.permissions)
        group.checkedCount = group.permissions.length
        group.checked = true
        group.indeterminate = false
      } else {
        permissionTree.setCheckedKeys([])
        group.checkedCount = 0
        group.checked = false
        group.indeterminate = false
      }
    },
    setUnCheckedChildRecursion(treeNode) {
      /* 设置子节点为未选中状态 */
      if (treeNode.childNodes) {
        treeNode.childNodes.forEach(item => {
          item.checked = false
          this.setUnCheckedChildRecursion(item)
        })
      }
    },
    setCheckedParentRecursion(treeNode) {
      /* 设置父节点为选中状态 */
      if (treeNode.parent) {
        treeNode.parent.checked = true
        this.setCheckedParentRecursion(treeNode.parent)
      }
    },
    async submitForm() {
      const dto = {
        permissions: []
      }
      for (const i in this.permissionData.groups) {
        const group = this.permissionData.groups[i]
        const checkedKeyMap = this.$refs.permissionTree[i].getCheckedKeys().reduce((total, currentValue, currentIndex) => {
          total[currentValue] = currentIndex
          return total
        }, {})
        group.permissions.forEach(permission => {
          if (permission.isGranted && checkedKeyMap[permission.name] === undefined) {
            dto.permissions.push({ isGranted: false, name: permission.name })
          } else if (!permission.isGranted && checkedKeyMap[permission.name] !== undefined) {
            dto.permissions.push({ isGranted: true, name: permission.name })
          }
        })
      }
      await edit(this.context.providerName, this.context.providerKey, dto)
      this.$message({ message: this.$t('AbpIdentity[\'Ok\']'), type: 'success' })
      this.closeDialog()
      this.$emit('saveSucceed')
    },
    closeDialog() {
      this.resetDialog()
      this.$emit('update:visible', false)
    },
    resetDialog() {
    }
  }
}
</script>

<style scoped>

</style>
